package main

import "fmt"

// 一个接口类型的变量能够存储所有实现了该接口的类型变量。

type Sayer interface {
	Say(string)
}

type dog struct{}

func (d dog) Say(s string) {
	fmt.Printf("狗说：%s\n", s)
}

type cat struct{}

func (c cat) Say(s string) {
	fmt.Printf("猫说：%s\n", s)
}

type Mover interface {
	Move()
}

func (d dog) Move() {
	fmt.Println("狗会动")
}

func (c *cat) Move() {
	fmt.Println("猫会动")
}

func main() {

	var x Sayer // 声明一个Sayer类型的变量x

	d := dog{}   // 声明一个Dog类型变量d
	x = d        // 可以把Dog类型变量直接赋值给x
	x.Say("汪汪汪") // 狗说：汪汪汪

	c := cat{}
	x = c
	x.Say("喵喵喵") // 猫说：喵喵喵

	var x1 Mover
	d1 := dog{}
	x1 = d1
	x1.Move()

	d2 := &dog{}
	x1 = d2
	x1.Move()

	c1 := &cat{}
	x1 = c1
	x1.Move()

	// c2 := cat{}  // c2是Cat类型
	// x1 = c2     // 不能将c2当成Mover类型
	// x1.Move()
}
